#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "Property.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Interface;
class ProtocolStateMachine;

/// <summary>
/// Port
/// A Port is a property of an EncapsulatedClassifier that specifies a distinct
/// interaction point between that EncapsulatedClassifier and its environment or
/// between the (behavior of the) EncapsulatedClassifier and its internal parts.
/// Ports are connected to Properties of the EncapsulatedClassifier by Connectors
/// through which requests can be made to invoke BehavioralFeatures. A Port may
/// specify the services an EncapsulatedClassifier provides (offers) to its
/// environment as well as the services that an EncapsulatedClassifier expects
/// (requires) of its environment.  A Port may have an associated
/// ProtocolStateMachine.
/// </summary>
class UMLMODEL_EXPORT Port : public Property {

public: // Constructors and destructors
    explicit Port(const QString& umlType="uml::Port");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// basicProvided
    /// The union of the sets of Interfaces realized by the type of the Port and its
    /// supertypes, or directly the type of the Port if the Port is typed by an
    /// Interface.
    /// </summary>
    virtual shared_ptr<vector<Interface>> basicProvided() const;

    /// <summary>
    /// basicRequired
    /// The union of the sets of Interfaces used by the type of the Port and its
    /// supertypes.
    /// </summary>
    virtual shared_ptr<vector<Interface>> basicRequired() const;

public: // Properties
    /// <summary>
    /// isBehavior getter
    /// Specifies whether requests arriving at this Port are sent to the classifier
    /// behavior of this EncapsulatedClassifier. Such a Port is referred to as a
    /// behavior Port. Any invocation of a BehavioralFeature targeted at a behavior Port
    /// will be handled by the instance of the owning EncapsulatedClassifier itself,
    /// rather than by any instances that it may contain.
    /// </summary>
    bool isBehavior() const;

    /// <summary>
    /// isBehavior setter
    /// Specifies whether requests arriving at this Port are sent to the classifier
    /// behavior of this EncapsulatedClassifier. Such a Port is referred to as a
    /// behavior Port. Any invocation of a BehavioralFeature targeted at a behavior Port
    /// will be handled by the instance of the owning EncapsulatedClassifier itself,
    /// rather than by any instances that it may contain.
    /// </summary>
    void setIsBehavior(bool value);

    /// <summary>
    /// isConjugated getter
    /// Specifies the way that the provided and required Interfaces are derived from the
    /// Port’s Type.
    /// </summary>
    bool isConjugated() const;

    /// <summary>
    /// isConjugated setter
    /// Specifies the way that the provided and required Interfaces are derived from the
    /// Port’s Type.
    /// </summary>
    void setIsConjugated(bool value);

    /// <summary>
    /// isService getter
    /// If true, indicates that this Port is used to provide the published functionality
    /// of an EncapsulatedClassifier.  If false, this Port is used to implement the
    /// EncapsulatedClassifier but is not part of the essential externally-visible
    /// functionality of the EncapsulatedClassifier and can, therefore, be altered or
    /// deleted along with the internal implementation of the EncapsulatedClassifier and
    /// other properties that are considered part of its implementation.
    /// </summary>
    bool isService() const;

    /// <summary>
    /// isService setter
    /// If true, indicates that this Port is used to provide the published functionality
    /// of an EncapsulatedClassifier.  If false, this Port is used to implement the
    /// EncapsulatedClassifier but is not part of the essential externally-visible
    /// functionality of the EncapsulatedClassifier and can, therefore, be altered or
    /// deleted along with the internal implementation of the EncapsulatedClassifier and
    /// other properties that are considered part of its implementation.
    /// </summary>
    void setIsService(bool value);

    /// <summary>
    /// protocol getter
    /// An optional ProtocolStateMachine which describes valid interactions at this
    /// interaction point.
    /// </summary>
    shared_ptr<ProtocolStateMachine> protocol() const;

    /// <summary>
    /// protocol setter
    /// An optional ProtocolStateMachine which describes valid interactions at this
    /// interaction point.
    /// </summary>
    void setProtocol(shared_ptr<ProtocolStateMachine> value);

    /// <summary>
    /// provided getter
    /// The Interfaces specifying the set of Operations and Receptions that the
    /// EncapsulatedCclassifier offers to its environment via this Port, and which it
    /// will handle either directly or by forwarding it to a part of its internal
    /// structure. This association is derived according to the value of isConjugated.
    /// If isConjugated is false, provided is derived as the union of the sets of
    /// Interfaces realized by the type of the port and its supertypes, or directly from
    /// the type of the Port if the Port is typed by an Interface. If isConjugated is
    /// true, it is derived as the union of the sets of Interfaces used by the type of
    /// the Port and its supertypes.
    /// </summary>
    vector<shared_ptr<Interface>>& provided();

    /// <summary>
    /// redefinedPorts getter
    /// A Port may be redefined when its containing EncapsulatedClassifier is
    /// specialized. The redefining Port may have additional Interfaces to those that
    /// are associated with the redefined Port or it may replace an Interface by one of
    /// its subtypes.
    /// </summary>
    vector<shared_ptr<Port>>& redefinedPorts();

    /// <summary>
    /// required getter
    /// The Interfaces specifying the set of Operations and Receptions that the
    /// EncapsulatedCassifier expects its environment to handle via this port. This
    /// association is derived according to the value of isConjugated. If isConjugated
    /// is false, required is derived as the union of the sets of Interfaces used by the
    /// type of the Port and its supertypes. If isConjugated is true, it is derived as
    /// the union of the sets of Interfaces realized by the type of the Port and its
    /// supertypes, or directly from the type of the Port if the Port is typed by an
    /// Interface.
    /// </summary>
    vector<shared_ptr<Interface>>& required();

private: // Fields
    /// <summary>
    /// isBehavior
    /// Specifies whether requests arriving at this Port are sent to the classifier
    /// behavior of this EncapsulatedClassifier. Such a Port is referred to as a
    /// behavior Port. Any invocation of a BehavioralFeature targeted at a behavior Port
    /// will be handled by the instance of the owning EncapsulatedClassifier itself,
    /// rather than by any instances that it may contain.
    /// </summary>
    const static bool isBehavior_default_;
    bool isBehavior_= isBehavior_default_;

    /// <summary>
    /// isConjugated
    /// Specifies the way that the provided and required Interfaces are derived from the
    /// Port’s Type.
    /// </summary>
    const static bool isConjugated_default_;
    bool isConjugated_= isConjugated_default_;

    /// <summary>
    /// isService
    /// If true, indicates that this Port is used to provide the published functionality
    /// of an EncapsulatedClassifier.  If false, this Port is used to implement the
    /// EncapsulatedClassifier but is not part of the essential externally-visible
    /// functionality of the EncapsulatedClassifier and can, therefore, be altered or
    /// deleted along with the internal implementation of the EncapsulatedClassifier and
    /// other properties that are considered part of its implementation.
    /// </summary>
    const static bool isService_default_;
    bool isService_= isService_default_;

    /// <summary>
    /// protocol
    /// An optional ProtocolStateMachine which describes valid interactions at this
    /// interaction point.
    /// </summary>
    shared_ptr<ProtocolStateMachine> protocol_;

    /// <summary>
    /// provided
    /// The Interfaces specifying the set of Operations and Receptions that the
    /// EncapsulatedCclassifier offers to its environment via this Port, and which it
    /// will handle either directly or by forwarding it to a part of its internal
    /// structure. This association is derived according to the value of isConjugated.
    /// If isConjugated is false, provided is derived as the union of the sets of
    /// Interfaces realized by the type of the port and its supertypes, or directly from
    /// the type of the Port if the Port is typed by an Interface. If isConjugated is
    /// true, it is derived as the union of the sets of Interfaces used by the type of
    /// the Port and its supertypes.
    /// </summary>
    vector<shared_ptr<Interface>> provided_;

    /// <summary>
    /// redefinedPorts
    /// A Port may be redefined when its containing EncapsulatedClassifier is
    /// specialized. The redefining Port may have additional Interfaces to those that
    /// are associated with the redefined Port or it may replace an Interface by one of
    /// its subtypes.
    /// </summary>
    vector<shared_ptr<Port>> redefinedPorts_;

    /// <summary>
    /// required
    /// The Interfaces specifying the set of Operations and Receptions that the
    /// EncapsulatedCassifier expects its environment to handle via this port. This
    /// association is derived according to the value of isConjugated. If isConjugated
    /// is false, required is derived as the union of the sets of Interfaces used by the
    /// type of the Port and its supertypes. If isConjugated is true, it is derived as
    /// the union of the sets of Interfaces realized by the type of the Port and its
    /// supertypes, or directly from the type of the Port if the Port is typed by an
    /// Interface.
    /// </summary>
    vector<shared_ptr<Interface>> required_;

};

} // namespace uml
